﻿#pragma once
#include "Comm.h"
#include "CommType.h"
#include "Atom.h"
#include "ThreadLock.h"

namespace COMM
{
	class COMM_API Thread
	{
		MYLIB_NONCOPIED_CLASS(Thread);
	public:
#ifdef COMM_MSVC
		typedef HANDLE handle;
#else
		typedef pthread_t handle;
#endif
		enum { EXIT_MIN = 0x7FFFFFF0, EXIT_CANCELED, EXIT_TIMEOUT, EXIT_ERROR, EXIT_MAX };
		enum State { TS_INIT = 0, TS_RUNNING, TS_EXIT };

		static void Sleep(unsigned int timeoutMs = -1);
		// pseudo id in __CYGWIN__ version.
		static int Id();
		typedef int(*ThreadProc)(CommType& arg);
		// ScopedPtr<Thread> should be used to release the returned instance after thread is run over.
		static Thread* Run(ThreadProc proc, const CommType& arg = CommType::Null, const char* threadName = NULL, bool suspend = false);

		Thread(const char* threadName = NULL, int stackSize = 0);
		virtual ~Thread(void);
		handle Handle() const;
		const char* Name() const;
		void Run();
		// cancel thread.
		void Terminate();
		// retrieve exit code, then you can re-run.
		int Join(unsigned int timeoutMs = -1);

	protected:
		virtual int Process() = 0;
	private:
#ifdef COMM_MSVC
		static DWORD WINAPI __ThreadProc(void* arg);
#else
		static void* __ThreadProc(void* arg);
#endif
		static int __ThreadProcComm(void* arg);
	private:
		ThreadLock m_lock;
		AtomInt m_tid;
		AtomInt m_state;
		String m_name;
		int m_size;
		handle m_thread;
		int m_exitcode;
	};
}


